package com.elinkway.infinitemovies.utils;

import com.elinkway.infinitemovies.async.RequestSniffApiContentTask;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 截流请求数据线程管理类
 * <p/>
 * Created by wangyemin on 2015/12/11.
 */
public class RequestSniffDataTaskPoolManager {

    public static RequestSniffDataTaskPoolManager mInstance;
    // 定义列表存放多线程执行结果集合
    public List<String> resultList; // api_content_list
    ThreadPoolExecutor executorpool;
    TimeUnit timeUnit = TimeUnit.MILLISECONDS;// 时间单位

    /**
     * 线程池初始化
     */
    public static final RequestSniffDataTaskPoolManager get() {
        if (mInstance == null) {
            mInstance = new RequestSniffDataTaskPoolManager();
        }
        return mInstance;
    }

    /**
     * 创建线程池
     */
    public void createPool() {
        LogUtils.e(Utils.TAG, " create pool ");
        resultList = new ArrayList();
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        RejectedExecutionHandlerImpl rejectionHandler = new RejectedExecutionHandlerImpl();
        int processors = Runtime.getRuntime().availableProcessors();
        int maxThreads = processors * 2;
        executorpool = new ThreadPoolExecutor(maxThreads, maxThreads, 5, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(maxThreads), threadFactory, rejectionHandler);
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        if (executorpool != null && !executorpool.isShutdown()) {
            executorpool.shutdownNow();
            if (resultList != null)
                LogUtils.e(Utils.TAG, " thread pool shut down api_content_list size " + resultList.size());
        }
    }

    /**
     * 当前线程池任务是否都已经执行完毕
     */
    public boolean isTerminated() {
        return executorpool == null ? true : executorpool.isTerminated();
    }


    /**
     * @param tasksList api_list
     * @param refer     sniffUrl
     * @param userAgent
     * @param timeOut   单个任务超时(当前设置时间为2s)
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public void exeTaskTimeOut(List<String> tasksList, String refer, String userAgent, final long timeOut) throws InterruptedException, ExecutionException {
        if (tasksList != null && tasksList.size() > 0) {
            resultList = new ArrayList<>(tasksList.size());
            for (int i = 0; i < tasksList.size(); i++) {
                if (executorpool != null) {
                    final Future<?> future = executorpool.submit(new RequestSniffApiContentTask(i, tasksList.get(i), refer, userAgent));
                    final int index = i;
                    new android.os.Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                future.cancel(true);
                                LogUtils.e(Utils.TAG, " thread future " + index + " task normal next ");
                            } catch (Exception e) {
                                LogUtils.e(Utils.TAG, " thread future " + index + " " + e.getMessage());
                            }
                        }
                    }, timeOut);
                }
            }
        }
    }

    /**
     * 统计线程执行结果
     *
     * @param apiContent
     */
    public synchronized void setResultList(String apiContent, int index) {
        if (resultList != null) {
            resultList.add(index, apiContent);
        }
    }

    public List<String> getResultList() {
        return resultList;
    }
}


class RejectedExecutionHandlerImpl implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        LogUtils.e(Utils.TAG, "reject thread " + r.toString() + " is rejected");
    }
}
